home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / TUTOR.C < prev    next >
C/C++ Source or Header  |  1997-08-18  |  40KB  |  1,605 lines

  1. #ifndef STANDALONE
  2. #include "global.h"
  3. #include "ctype.h"
  4. #ifdef MSDOS
  5. #include <dir.h>
  6. #include <dos.h>
  7. #else
  8. #include <time.h>
  9. #endif
  10. #ifndef _lint
  11. #define SKIP_HACK 1        /* a quick hack to get around a compiler warning */
  12. #endif
  13. #include "commands.h"
  14. #include "files.h"
  15. #include "mailbox.h"
  16. #include "usock.h"
  17. #include "pktdrvr.h"
  18. #include "color.h"
  19. #include "x.h"
  20. #ifdef SQL
  21. #include "sql.h"
  22. #endif
  23. #ifndef MSDOS
  24. #include "ftp.h"
  25. #include "session.h"
  26. #endif
  27. #endif
  28.  
  29.  
  30. #if !defined(_lint)
  31. static char rcsid[] OPTIONAL = "$Id: tutor.c,v 1.25 1997/08/19 01:19:22 root Exp root $";
  32. #endif
  33.  
  34. struct world {
  35.     int mode;
  36.     char color;
  37.     char colorblock;
  38.     char last[2];
  39.     char inescape;
  40.     char ipconnect;
  41.     char *subdir;
  42.     char const *call;
  43.     time_t starttime;
  44.     int ischild;
  45. #ifndef STANDALONE
  46.     struct mbx *m;
  47. #endif
  48.     FILE *fp;
  49.     FILE *out;
  50.     char *Tutors[100];
  51.     int maxselect;
  52.     char *variables[10];
  53.     long indexes[10];
  54. #ifdef old
  55.     int socket[10];
  56. #else
  57.     int *socket;
  58. #endif
  59.     int user;
  60.     int whichsocket;
  61.     int background;
  62.     int goback;
  63.     int lostconnection;
  64.     char Error[80];
  65. };
  66.  
  67.  
  68.  
  69. #ifndef STANDALONE
  70. int Tutored = 0;
  71. static int inMbScriptHook = 0;
  72. extern int Stutor, Sinfo, Snews, Tutorlogins[];
  73. extern char Tcall[AXALEN], Icall[AXALEN], Ncall[AXALEN];
  74. #endif
  75.  
  76. extern int sockblock (int s, int value);
  77.  
  78. #ifdef TUTOR
  79. static void mycolorchange (struct world *here, const char *input, char *last);
  80. static void mytprintf (struct world *here, const char *str);
  81.  
  82. #ifndef STANDALONE
  83. static void mygets (char *buf, int size, struct world *here);
  84. #else
  85. void mygets (char *buf, int size, struct world *here);
  86. #endif
  87.  
  88. #ifdef SQL
  89. static void expand_buf (char *buf, struct world *here);
  90. #endif
  91.  
  92. static char *nextarg (char *cp, long *i);
  93. static char *nextnum (char *cp, int defval, struct world *here, long *i);
  94. static long getnum (char *cp, int defval, struct world *here);
  95. static int scriptconn (int argc, char *argv[], void *p);
  96. static char *getnext (char *cp, char **put, struct world *here);
  97. static void process (struct world *here);
  98. static void buildmenu (struct world *here);
  99.  
  100. #ifndef STANDALONE
  101. void tutorserv (const char *call, struct mbx *m, int mode, int color, int ip);
  102. #else
  103. void tutorserv (const char *call, int mode, int color, int ip);
  104. #endif
  105.  
  106. static int scriptcmd (struct world *inherited, FILE * fp, const char *name);
  107.  
  108. #ifndef STANDALONE
  109. int dombscript (int argc, char *argv[], void *p);
  110. int proxy (FILE * fp, const char *from);
  111. #endif
  112. #endif /* TUTOR */
  113.  
  114.  
  115. #ifdef TUTOR
  116.  
  117. static void
  118. mycolorchange (struct world *here, const char *input, char *last)
  119. {
  120.     if (here->color)
  121.         (void) colorchange (input, last);
  122. }
  123.  
  124.  
  125.  
  126. static void
  127. mytprintf (struct world *here, const char *str)
  128. {
  129.     if (here->background && !here->whichsocket)
  130.         return;
  131.     if (!here->colorblock)
  132.         tprintf (str);
  133.     else if (colorprintf (&here->inescape, here->color, (const unsigned char *) str))
  134.         here->last[0] = 0;
  135. }
  136. #endif
  137.  
  138.  
  139.  
  140. char *
  141. skipwhite (char IFLINT(const) *cp)
  142. {
  143.     while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
  144.         cp++;
  145.     return (cp);        /*lint !e605 */
  146. }
  147.  
  148.  
  149.  
  150. char *
  151. skipnonwhite (char IFLINT(const) *cp)
  152. {
  153.     while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
  154.         cp++;
  155.     return (cp);        /*lint !e605 */
  156. }
  157.  
  158.  
  159.  
  160. void
  161. trimright (char *cp)
  162. {
  163.     while (cp[strlen (cp) - 1] == ' ')
  164.         cp[strlen (cp) - 1] = 0;
  165. }
  166.  
  167.  
  168.  
  169. void
  170. trimrightCR (char *cp)
  171. {
  172.     rip (cp);
  173.     trimright (cp);
  174.     strcat (cp, "\n");
  175. }
  176.  
  177.  
  178.  
  179. #ifdef TUTOR
  180. #ifndef STANDALONE
  181. static int tutor_recvline (int s, char *buf, unsigned size);
  182.  
  183.  
  184. static int
  185. tutor_recvline (int s, char *buf, unsigned size)
  186. {
  187. char *origbuf = buf;
  188. int c, cnt = 0, opt, cl;
  189.  
  190.     usflush (Curproc->output);
  191.  
  192.     for ( ; ; ) {
  193.         if (nullsocket (s)) {
  194.             c = EOF;
  195.             cnt = 0;
  196.             break;
  197.         }
  198.         c = recvchar (s);
  199.         if (c == EOF) {
  200.             if (errno == EWOULDBLOCK)
  201.                 continue;
  202.             break;
  203.         }
  204.         kwait (NULL);
  205.         if (c == IAC) {    /* Telnet command escape */
  206.             if ((c = recvchar (s)) == EOF)
  207.                 break;
  208.             if (c >= 250 && c < 255 && (opt = recvchar (s)) != EOF) {
  209.                 switch (c) {
  210.                     case SB:
  211.                         opt = recvchar (s);
  212.                         if (opt == EOF)
  213.                             break;
  214.                         cl = opt;
  215.                         c = recvchar (s);
  216.                         while ((c != EOF) && !(cl == IAC && c == SE)) {
  217.                             cl = c;
  218.                             c = recvchar (s);
  219.                         }
  220.                         break;
  221.                     case WILL:
  222.                         if (opt == TN_LINEMODE) {
  223.                             tprintf ("%c%c%c", IAC, DO, opt);
  224.                             tprintf ("%c%c%c%c%c%c%c", IAC, SB, TN_LINEMODE, 1, 1, IAC, SE);
  225.                         } else
  226.                             tprintf ("%c%c%c", IAC, DONT, opt);
  227.                         break;
  228.                     case WONT:
  229.                         tprintf ("%c%c%c", IAC, DONT, opt);
  230.                         break;
  231.                     case DO:
  232.                         tprintf ("%c%c%c", IAC, WONT, opt);
  233.                         break;
  234.                     case DONT:
  235.                         tprintf ("%c%c%c", IAC, WONT, opt);
  236.                         break;
  237.                     default:
  238.                         break;
  239.                 }
  240.                 usflush (Curproc->output);
  241.                 kwait (NULL);
  242.                 continue;
  243.             }
  244.             if (c != IAC && (c = recvchar (s)) == EOF)
  245.                 break;
  246.         }
  247.         *buf++ = (char) c;
  248.         ++cnt;
  249.         if (c == '\n')
  250.             break;
  251.         if ((unsigned) cnt == (size - 1)) {
  252.             cnt = -2;
  253.             break;
  254.         }
  255.         /* the following is a special case HACK for telnet logins */
  256.         if (!strncmp (origbuf, "login: ", 7) || !strncmp (origbuf, "Password: ", 10))
  257.             break;
  258.     }
  259.     if (c == EOF && cnt == 0)
  260.         return -1;
  261.     *buf = '\0';
  262.     return cnt;
  263. }
  264.  
  265.  
  266.  
  267. static void
  268. mygets (char *buf, int size, struct world *here)
  269. {
  270.     if ((here->background && !here->whichsocket) || here->user < 0) {
  271.         buf[0] = 0;
  272.         return;
  273.     }
  274.     usflush (Curproc->output);
  275. #ifdef MBXTDISC
  276.     /* Restart the inactivity timer */
  277.     if (here->m != NULLMBX)
  278.         start_timer (&here->m->tdisc);
  279. #endif
  280.  
  281.  
  282.     if ((size = tutor_recvline (here->user ? here->user : Curproc->input, buf, (unsigned) size)) < 0) {
  283.         if (here->user > 0) {
  284.             here->socket[here->whichsocket] = here->user = -1;
  285.             Curproc->output = here->socket[0];
  286.         }
  287.         buf[0] = 0;
  288.         here->lostconnection = -1;
  289.     }
  290.     rip (buf);
  291. }
  292. #endif /* STANDALONE */
  293.  
  294.  
  295.  
  296. static char *
  297. nextarg (char *cp, long *i)
  298. {
  299.     cp = skipnonwhite (cp);
  300.     cp = skipwhite (cp);
  301.     *i = atol (cp);
  302.     return (cp);
  303. }
  304.  
  305.  
  306.  
  307. static char *
  308. nextnum (char *cp, int defval, struct world *here, long *i)
  309. {
  310.     cp = skipnonwhite (cp);
  311.     cp = skipwhite (cp);
  312.     *i = getnum (cp, defval, here);
  313.     return (cp);
  314. }
  315.  
  316.  
  317.  
  318. static long
  319. getnum (char *cp, int defval, struct world *here)
  320. {
  321. long l = defval;
  322.  
  323.     switch (*cp) {
  324.         case '~':
  325.             if (tolower (cp[1]) == 'i') {
  326.                 l = here->indexes[cp[2] - '0'];
  327.                 break;
  328.             }
  329.             if (cp[1] >= '0' && cp[1] <= '9') {
  330.                 l = atol (here->variables[cp[1] - '0']);
  331.                 break;
  332.             }
  333.             break;
  334.         case 0:
  335.             break;
  336.         default:
  337.             l = atol (cp);
  338.             break;
  339.     }
  340.     return l;
  341. }
  342.  
  343.  
  344.  
  345. static char SCONFail[] = "SCRIPT connect failed: ";
  346. static char SCONFail2[] = "SCRIPT disconnect failed: ";
  347.  
  348.  
  349. /* open a network connection based upon information in the cc line.
  350.  * m->user is set to the socket number.
  351.  */
  352. static int
  353. scriptconn (int argc, char *argv[], void *p)
  354. {
  355. struct world *here;
  356. char sock[MAXSOCKSIZE];
  357. union sp sp;
  358. char ctype;
  359. struct iface *ifp;
  360. char digis[MAXDIGIS][AXALEN];
  361. char target[AXALEN];
  362. int ndigis, i;
  363.  
  364.     here = (struct world *) p;
  365.     sp.p = sock;
  366.     here->Error[0] = 0;    /* null error string */
  367.     ctype = (char) tolower (*argv[0]);
  368.     if (argc < 2) {
  369.         sprintf (here->Error, "%sSyntax Error", SCONFail);
  370.         return -1;
  371.     }
  372.     switch (ctype) {
  373. #ifdef AX25
  374.         case 'a':
  375.         case 'c':    /* allow 'c' for 'connect' as well */
  376.             if (((ifp = if_lookup (argv[1])) == NULLIF) || (ifp->flags & HIDE_PORT)) {
  377.                 sprintf (here->Error, "%sUnknown port %s", SCONFail, argv[1]);
  378.                 return -1;
  379.             }
  380.             if (ifp->type != CL_AX25) {
  381.                 sprintf (here->Error, "%sPort %s not usable for AX.25 connects", SCONFail, argv[1]);
  382.                 return -1;
  383.             }
  384.             if (setcall (target, argv[2]) == -1) {
  385.                 sprintf (here->Error, "%sBad call %s", SCONFail, argv[2]);
  386.                 return -1;
  387.             }
  388.             /* If digipeaters are given, put them in the routing table */
  389.             if (argc > 3) {
  390.                 ndigis = argc - 3;
  391.                 if (ndigis > MAXDIGIS) {
  392.                     sprintf (here->Error, "%sToo many digipeaters", SCONFail);
  393.                     return -1;
  394.                 }
  395.                 for (i = 0; i < ndigis; i++) {
  396.                     if (setcall (digis[i], argv[i + 3]) == -1) {
  397.                         sprintf (here->Error, "%sBad digipeater call %s", SCONFail, argv[i + 3]);
  398.                         return -1;
  399.                     }
  400.                 }
  401.                 if (ax_add (target, AX_AUTO, digis, ndigis, ifp) == NULLAXR) {
  402.                     sprintf (here->Error, "%sAX25 route add failed", SCONFail);
  403.                     return -1;
  404.                 }
  405.             }
  406.             sp.ax->sax_family = AF_AX25;
  407.             strncpy (sp.ax->iface, argv[1], ILEN - 1);    /* the interface name */
  408.             (void) setcall (sp.ax->ax25_addr, argv[2]);    /* the remote callsign */
  409.             if ((here->user = socket (AF_AX25, SOCK_STREAM, 0)) == -1) {
  410.                 sprintf (here->Error, "%sError allocating socket", SCONFail);
  411.                 return -1;
  412.             }
  413.             break;
  414. #endif
  415.         default:
  416.             sp.in->sin_family = AF_INET;
  417.             if ((sp.in->sin_addr.s_addr = resolve (argv[1])) == 0) {
  418.                 sprintf (here->Error, "%sHost Unknown", SCONFail);
  419.                 return -1;
  420.             }
  421.             /* get the optional port number */
  422.             if (argc > 2)
  423.                 sp.in->sin_port = (int16) atoip (argv[2]);
  424.             else
  425.                 sp.in->sin_port = IPPORT_TELNET;
  426.             if ((here->user = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
  427.                 sprintf (here->Error, "%sError allocating socket", SCONFail);
  428.                 return -1;
  429.             }
  430.     }
  431.  
  432.     (void) sockmode (here->user, SOCK_ASCII);
  433.  
  434.     if (connect (here->user, sp.p, SOCKSIZE) == -1) {
  435.         sprintf (here->Error, "SCRIPT connect failed: %s errno %d",
  436.              sockerr (here->user), errno);
  437.         close_s (here->user);
  438.         return -1;
  439.     }
  440.     return here->user;
  441. }
  442.  
  443.  
  444. static struct cmds sconcmds[] =
  445. {
  446.     { "tcp",    scriptconn, 0, 0, NULLCHAR },
  447.     { "telnet",    scriptconn, 0, 0, NULLCHAR },
  448. #ifdef AX25
  449.     { "ax25",    scriptconn, 0, 0, NULLCHAR },
  450.     { "connect",    scriptconn, 0, 0, NULLCHAR },
  451. #endif
  452.     { NULLCHAR,    NULL,        0, 0, NULLCHAR }
  453. };
  454.  
  455.  
  456.  
  457. static char *
  458. getnext (char *cp, char **put, struct world *here)
  459. {
  460. char *retval = cp, buf[4], c;
  461. time_t tm;
  462.  
  463.     buf[1] = 0;
  464.     if (*cp != '~') {
  465.         buf[0] = *cp;
  466.         *put = strdup (buf);
  467.     } else {
  468.         cp++;
  469.         retval++;
  470.         c = (char) tolower (*cp);
  471.         (void) time (&tm);
  472.         cp = ctime (&tm);
  473.         rip (cp);
  474.         cp[10] = cp[19] = 0;
  475.         switch (c) {
  476.             case 'l':    /* elapsed time of script */
  477.                 *put = (char *) mallocw (20);
  478.                 sprintf (*put, "%-ld", (tm - here->starttime));
  479.                 break;
  480.             case 'p':    /* current data file position */
  481.                 *put = (char *) mallocw (20);
  482.                 if (here->out)
  483.                     sprintf (*put, "%-ld", ftell (here->out));
  484.                 else
  485.                     strcpy (*put, "-1");
  486.                 break;
  487.             case 'c':
  488.                 *put = strdup (here->call);
  489.                 break;
  490.             case 'e':
  491.                 *put = strdup (here->Error);
  492.                 break;
  493.             case '~':
  494.             case 'b':
  495.                 buf[0] = (c == 'b') ? '\007' : *retval;
  496.                 *put = strdup (buf);
  497.                 break;
  498.             case 'h':
  499.                 *put = strdup (Hostname);
  500.                 break;
  501.             case 'd':
  502.                 strcat (cp, ", ");
  503.                 strcat (cp, &cp[20]);
  504.                 *put = strdup (cp);
  505.                 break;
  506.             case 't':
  507.                 *put = strdup (&cp[11]);
  508.                 break;
  509.             case 'n':
  510.                 buf[0] = '\n';
  511.                 *put = strdup (buf);
  512.                 break;
  513.             case 'u':    /* un-terminate this line */
  514.                 rip (retval);
  515.                 buf[0] = *(++retval);
  516.                 *put = strdup (buf);
  517.                 break;
  518.             case '0':
  519.             case '1':
  520.             case '2':
  521.             case '3':
  522.             case '4':
  523.             case '5':
  524.             case '6':
  525.             case '7':
  526.             case '8':
  527.             case '9':
  528.                 if (here->variables[c - '0'])
  529.                     *put = strdup (here->variables[c - '0']);
  530.                 else
  531.                     *put = strdup ("");
  532.                 break;
  533.             case 'i':
  534.                 if (retval[1] >= '0' && retval[1] <= '9') {
  535.                     *put = (char *) mallocw (20);
  536.                     sprintf (*put, "%-ld", here->indexes[*(++retval) - '0']);
  537.                     break;
  538.                 }
  539.                 /* else fall through */
  540.             default:
  541.                 sprintf (buf, "~%c", *retval);
  542.                 *put = strdup (buf);
  543.                 break;
  544.         }
  545.     }
  546.     return (retval);
  547. }
  548.  
  549.  
  550.  
  551. #ifdef SQL
  552. static void
  553. expand_buf (char *buf, struct world *here)
  554. {
  555. char *cp, *put;
  556. char newbuf[256];
  557.  
  558.     cp = buf;
  559.     newbuf[0] = 0;
  560.     while (*cp) {
  561.         cp = getnext (cp, &put, here);
  562.         strcat (newbuf, put);
  563.         free (put);
  564.         cp++;
  565.     }
  566.     strcpy (buf, newbuf);
  567. }
  568. #endif
  569.  
  570.  
  571.  
  572. static void
  573. process (struct world *here)
  574. {
  575. FILE *fp;
  576. int done = 0, skipping = 0, k, disconexit = 1;
  577. long j, i, l;
  578. char buf[256], c, *cp, lastresponse = 'y', *label = 0;
  579. char *put, *replyto;
  580. long pos;
  581.  
  582.     (void) time (&here->starttime);
  583.     if (!here->ischild) {
  584. #if 0
  585.         for (k = 0; k < 10; k++) {
  586.             here->variables[k] = 0;
  587.             here->indexes[k] = 1;
  588.             here->socket[k] = 0;
  589.         }
  590. #endif
  591.     } else {
  592.         here->user = 0;
  593.         disconexit = 0;
  594.     }
  595.  
  596.     here->socket[0] = Curproc->output;
  597. #if 0
  598.     if (here->user) {    /* inherited a socket from a parent script! */
  599.         Curproc->output = here->socket[1] = here->user;
  600.         here->whichsocket = 1;
  601.  
  602.         Curproc->output = here->socket[here->whichsocket];
  603.         disconexit = 0;
  604.     }
  605. #endif
  606.  
  607.     while (!done && fgets (buf, 256, here->fp)) {
  608. #ifdef MBXTDISC
  609.         /* Restart the inactivity timer */
  610.         if (here->m != NULLMBX)
  611.             start_timer (&here->m->tdisc);
  612. #endif
  613.         kwait (NULL);
  614.         if (buf[0] != '~' || ((buf[1] == '~') || isdigit (buf[1]))) {
  615.             if (!skipping) {
  616.                 cp = buf;
  617.                 while (*cp) {
  618.                     cp = getnext (cp, &put, here);
  619.                     mytprintf (here, put);
  620.                     free (put);
  621.                     cp++;
  622.                 }
  623.             }
  624.             continue;
  625.         }
  626.         c = (char) tolower (buf[1]);
  627.         cp = skipwhite (&buf[2]);
  628.         rip (cp);
  629.         if (skipping && c != 'l')
  630.             continue;
  631.         k = *cp - '0';
  632.         if (k > 9)
  633.             k = 0;
  634.         switch (c) {
  635.             case 'i':    /* modify an index counter
  636.                        index array in k, already */
  637.                 cp++;
  638.                 rip (cp);
  639.                 cp = skipwhite (cp);
  640.                 c = *cp++;
  641.                 cp = skipwhite (cp);
  642.                 if (!strnicmp (cp, "~p", 2)) {
  643.                     if (here->out)
  644.                         l = ftell (here->out);
  645.                     else
  646.                         l = -1;
  647.                 } else
  648.                     l = getnum (cp, 1, here);
  649.                 switch (c) {
  650.                     case '=':    /* assign */
  651.                         here->indexes[k] = l;
  652.                         break;
  653.                     case '+':    /* add */
  654.                         here->indexes[k] += l;
  655.                         break;
  656.                     case '-':    /* subtract */
  657.                         here->indexes[k] -= l;
  658.                         break;
  659.                     case '?':    /* compare */
  660.                         c = lastresponse = (here->indexes[k] == l) ? 'y' : 'n';
  661.                         cp = skipnonwhite (cp);
  662.                         cp = skipwhite (cp);
  663.                         if (*cp && c == 'y')
  664.                             goto another;
  665.                         break;
  666.                     default:
  667.                         break;
  668.                 }
  669.                 break;
  670.             another: case 'y':    /* on yes, goto label *//*lint !e616 */
  671.             case 'n':    /* on no, goto label */
  672.                 if (lastresponse != c)
  673.                     break;
  674.             case 'g':    /* goto label *//*lint !e616 */
  675.                 skipping = 1;
  676.                 free (label);
  677.                 label = strdup (cp);
  678.                 rewind (here->fp);
  679.                 break;
  680.             case 'l':    /* label line */
  681.                 if (skipping && !stricmp (cp, label)) {
  682.                     free (label);
  683.                     label = 0;
  684.                     skipping = 0;
  685.                 }
  686.                 break;
  687.             case 'b':    /* output 'n' blank lines */
  688.                 k = (int) getnum (cp, 0, here);
  689.                 if (!k)
  690.                     k = 1;
  691.                 while (k--)
  692.                     mytprintf (here, "\n");
  693.                 break;
  694.             case 'm':    /* more prompt */
  695.                 mytprintf (here, "\n---MORE (*y/n)---\n");
  696.                 mygets (buf, 256, here);
  697.                 if (here->lostconnection)
  698.                     goto lost;
  699.                 kwait (NULL);
  700.                 if (tolower (buf[0]) != 'n')
  701.                     break;
  702.             case 'x':    /* exit at this point *//*lint !e616 */
  703.                 /*                    done = 1;    */
  704.                 skipping = 1;
  705.                 free (label);
  706.                 label = strdup ("exit");
  707.                 break;
  708.             case 'q':    /* query with string for y/n answer */
  709.                 mytprintf (here, cp);
  710.                 mytprintf (here, " (*y/n)\n");
  711.                 mygets (buf, 256, here);
  712.                 if (here->lostconnection)
  713.                     goto lost;
  714.                 kwait (NULL);
  715.                 lastresponse = (tolower (buf[0]) == 'n') ? 'n' : 'y';
  716.                 break;
  717.             case 'j':    /* just compare first characters */
  718.             case 'c':    /* compare entire strings
  719.                        first string value in k, already */
  720.                 cp = nextarg (cp, &l);
  721.                 if (!here->variables[l] || !here->variables[k])
  722.                     lastresponse = 'n';
  723.                 else {
  724.                     if (c == 'c')
  725.                         c = lastresponse = (stricmp (here->variables[l], here->variables[k])) ? 'n' : 'y';
  726.                     else {
  727.                         cp = nextnum (cp, 0, here, &j);
  728.                         c = lastresponse = (strnicmp (here->variables[l], here->variables[k], (unsigned) j)) ? 'n' : 'y';
  729.                     }
  730.                     cp = skipnonwhite (cp);
  731.                     cp = skipwhite (cp);
  732.                     if (*cp && c == 'y')
  733.                         goto another;
  734.                 }
  735.                 break;
  736.             case 'h':    /* string has substring?
  737.                        first string value in k, already */
  738.                 cp = nextarg (cp, &l);
  739.                 if (!here->variables[l] || !here->variables[k])
  740.                     lastresponse = 'n';
  741.                 else {
  742.                     i = (int) strstr (here->variables[k], here->variables[l]);
  743.                     c = lastresponse = (!i) ? 'n' : 'y';
  744.                     if (i)
  745.                         i -= (int) here->variables[k];
  746.                     cp = nextarg (cp, &j);
  747.                     here->indexes[j] = i;
  748.                     cp = skipnonwhite (cp);
  749.                     cp = skipwhite (cp);
  750.                     if (*cp && c == 'y')
  751.                         goto another;
  752.                 }
  753.                 break;
  754.             case 'p':    /* pick out a sub-string
  755.                        to variable already in k */
  756.                 cp = nextarg (cp, &j);    /* from variable */
  757.                 cp = nextnum (cp, 0, here, &i);    /* start index */
  758.                 cp = nextnum (cp, 0, here, &l);    /* length */
  759.                 if ((int) (strlen (here->variables[j]) - (unsigned long) i) < l)
  760.                     l = (long) (strlen (here->variables[j]) - (unsigned long) i);
  761.                 l++;    /* allow room for zero byte */
  762.                 free (here->variables[k]);
  763.                 here->variables[k] = (char *) mallocw ((unsigned) l);
  764.                 strncpy (here->variables[k], &here->variables[j][i], (unsigned) l);
  765.                 here->variables[k][l - 1] = 0;
  766.                 break;
  767.             case 't':    /* truncate a variable string */
  768.                 cp = nextnum (cp, 0, here, &j);
  769.                 if ((int) strlen (here->variables[k]) > j)
  770.                     here->variables[k][j] = 0;
  771.                 break;
  772.             case 'z':    /* get length of variable and place in index */
  773.                 cp = nextarg (cp, &j);
  774.                 here->indexes[j] = (long) ((here->variables[k]) ? strlen (here->variables[k]) : 0);
  775.                 break;
  776.             case 'a':    /* assign a string to a variable */
  777.                 /* or append if 'ap str1 str2' */
  778.                 if ((cp == &buf[2]) && (tolower (*cp) == 'p')) {
  779.                     cp = skipwhite (++cp);
  780.                     if (*cp) {
  781.                         k = *cp - '0';
  782.                         cp = skipwhite (++cp);
  783.                         if (*cp) {
  784.                             l = *cp - '0';
  785.                             cp = (char *) mallocw (strlen (here->variables[k]) +
  786.                                           strlen (here->variables[l]) + 1);
  787.                             strcpy (cp, here->variables[k]);
  788.                             strcat (cp, here->variables[l]);
  789.                             free (here->variables[k]);
  790.                             here->variables[k] = cp;
  791.                         }
  792.                     }
  793.                     break;
  794.                 }    /* else fall through */
  795.             case 'v':    /* prompt and place result in variable */
  796.                 free (here->variables[k]);
  797.                 cp++;
  798.                 cp = skipwhite (cp);
  799.                 if (c == 'a') {
  800.                     if (*cp == '~')
  801.                         (void) getnext (cp, &here->variables[k], here);
  802.                     else
  803.                         here->variables[k] = strdup (cp);
  804.                 } else {
  805.                     if (*cp) {
  806.                         mytprintf (here, cp);
  807.                         mytprintf (here, "\n");
  808.                     }
  809.                     mygets (buf, 256, here);
  810.                     if (here->lostconnection)
  811.                         goto lost;
  812.                     kwait (NULL);
  813.                     here->variables[k] = strdup (buf);
  814.                 }
  815.                 break;
  816.             case 'd':    /* deliver a mail file */
  817.                 /* first check to see if this is a 'dr' command */
  818.                 replyto = NULLCHAR;
  819.                 if ((cp == &buf[2]) && (tolower (buf[2]) == 'r')) {
  820.                     /* this contains a reply-to string */
  821.                     cp = skipwhite (++cp);
  822.                     (void) getnext (cp, &replyto, here);    /* allow ~c and ~# subs */
  823.                     if (replyto == NULLCHAR || strlen (replyto) == 1) {
  824.                         char *cp2;
  825.  
  826.                         free (replyto);
  827.                         replyto = strdup (cp);
  828.                         cp2 = strchr (replyto, ' ');
  829.                         if (cp2)
  830.                             *cp2++ = 0;
  831.                         cp = cp2;
  832.                     } else    /* point to 'to' user's parameter */
  833.                         cp = strchr (cp, ' ');
  834.                     cp = skipwhite (cp);
  835.                 }
  836.                 (void) getnext (cp, &put, here);    /* allow ~c and ~# subs */
  837.                 if (strlen (put) == 1) {
  838.                     char *cp2;
  839.  
  840.                     free (put);
  841.                     put = strdup (cp);
  842.                     cp2 = strchr (put, ' ');
  843.                     if (cp2)
  844.                         *cp2++ = 0;
  845.                     cp = cp2;
  846.                 } else
  847.                     cp = strchr (cp, ' ');
  848.                 cp = skipwhite (cp);
  849.                 lastresponse = 'n';    /* default to fails */
  850.                 /* get filename and open it */
  851.                 if (cp) {    /* if filename given */
  852.                     FILE *out2;
  853.  
  854.                     out2 = NULLFILE;
  855.                     if (stricmp (cp, "null"))
  856.                         out2 = fopen (cp, READ_TEXT);
  857.                     /* save current pos, and get tutor description */
  858.                     pos = ftell (here->fp);
  859.                     rewind (here->fp);
  860.                     (void) fgets (buf, 256, here->fp);
  861.                     fseek (here->fp, pos, SEEK_SET);
  862.                     cp = skipwhite (buf);
  863.                     rip (cp);
  864.                     /* now mail the file */
  865.                     (void) rdaemon (out2, replyto, NULLCHAR, put, cp, 'P', 0);
  866.                     lastresponse = 'y';
  867.                     if (out2 != NULLFILE)
  868.                         (void) fclose (out2);
  869.                 }
  870.                 free (put);
  871.                 break;
  872.  
  873.             case 'e':    /* is io file at end of file */
  874.                 if (here->out != NULLFILE) {
  875.                     c = lastresponse = (feof (here->out)) ? 'y' : 'n';
  876.                     if (*cp && c == 'y')
  877.                         goto another;
  878.                 }
  879.                 break;
  880.             case 's':    /* seek to start of io file or sql query */
  881. #ifdef SQL
  882.                 if (tolower (*cp) == 'q') {
  883.                     /* sql query */
  884.                     cp = skipnonwhite (cp);
  885.                     cp = skipwhite (cp);
  886.                     expand_buf (cp, here);
  887.                     usflush (Curproc->output);
  888.                     (void) sql_query (cp);
  889.                 } else
  890. #endif
  891.                 if (here->out != NULLFILE) {
  892.                     switch (tolower (*cp)) {
  893.                         case 'e':
  894.                             fseek (here->out, 0L, 2);
  895.                             break;
  896.                         case 'p':
  897.                             cp = skipwhite (++cp);
  898.                             if (*cp) {
  899.                                 k = *cp - '0';
  900.                                 fseek (here->out, here->indexes[k], 0);
  901.                                 break;
  902.                             }    /* else, fall through */
  903.                         default:
  904.                             rewind (here->out);
  905.                     }
  906.                 }
  907.                 break;
  908.             case 'u':    /* upload a text file */
  909.                 if ((fp = fopen (cp, READ_TEXT)) != NULLFILE) {
  910. #ifndef STANDALONE
  911.                     (void) sendfile (fp, Curproc->output, ASCII_TYPE, 0);
  912. #else
  913.                     (void) sendfile (fp);
  914. #endif
  915.                     (void) fclose (fp);
  916.                 }
  917.                 break;
  918.             case 'o':    /* open an old io file */
  919.             case 'f':    /* create a new io file */
  920.                 if (here->out != NULLFILE)
  921.                     (void) fclose (here->out);
  922.                 here->out = NULLFILE;
  923.                 if (*cp == '~' && isdigit (cp[1]))
  924.                     cp = here->variables[cp[1] - '0'];
  925.                 here->out = fopen (cp, (c == 'f') ? CREATE_TEXT : UPDATE_TEXT);
  926.                 lastresponse = (here->out == NULLFILE) ? 'n' : 'y';
  927.                 break;
  928.             case 'w':    /* write a textline to the io file */
  929.                 if (here->out != NULLFILE)
  930.                     while (*cp) {
  931.                         cp = getnext (cp, &put, here);
  932.                         fprintf (here->out, put);
  933.                         free (put);
  934.                         cp++;
  935.                     }
  936.                 break;
  937.             case 'r':    /* read a line from io file in var */
  938.                 if (here->out != NULLFILE) {
  939.                     free (here->variables[k]);
  940.                     (void) fgets (buf, 256, here->out);
  941.                     rip (buf);
  942.                     here->variables[k] = strdup (buf);
  943.                 }
  944.                 break;
  945.             case 'k':    /* kill a file */
  946.                 unlink (cp);
  947.                 lastresponse = (access (cp, 0)) ? 'y' : 'n';
  948.                 break;
  949.             case '?':
  950.                 switch (tolower (*cp)) {
  951.                     case 'c':
  952.                         lastresponse = (!here->color) ? 'n' : 'y';
  953.                         break;
  954.                     case 'i':
  955.                         lastresponse = (here->ipconnect) ? 'y' : 'n';
  956.                         break;
  957.                     default:
  958.                         break;
  959.                 }
  960.                 break;
  961.             case '!':
  962.                 switch (tolower (*cp)) {
  963.                     case 'c':
  964.                         here->color = 1;
  965.                         break;
  966.                     default:
  967.                         break;
  968.                 }
  969.                 break;
  970.             case '*':
  971.                 switch (tolower (*cp)) {
  972.                     case 'b':
  973.                         here->colorblock = 1;
  974.                         break;
  975.                     case 'e':
  976.                         here->colorblock = 0;
  977.                         break;
  978.                     default:
  979.                         break;
  980.                 }
  981.                 break;
  982.             case '%':
  983.                 lastresponse = (!here->color) ? 'n' : 'y';
  984.                 if (here->color)
  985.                     colorfile (cp, here->last);
  986.                 break;
  987.             case '@':
  988.                 mycolorchange (here, cp, here->last);
  989.                 break;
  990.             case '$':{
  991.                     char *args[2];
  992.                     int lastback;
  993.  
  994.                     lastback = here->goback;
  995.                     here->goback = 0;
  996.                     if (*cp == '$') {
  997.                         here->goback = 1;
  998.                         cp = skipwhite (++cp);
  999.                     }
  1000.                     args[1] = cp;
  1001.                     if (access (cp, 4))
  1002.                         lastresponse = 'n';
  1003.                     else {
  1004.                         Curproc->output = here->socket[0];
  1005.                         (void) doscript (0, args, here);
  1006.                         lastresponse = 'y';
  1007.                         Curproc->output = here->socket[0];
  1008.                     }
  1009.                     here->goback = lastback;
  1010.                 }
  1011.                 break;
  1012.             case ')':
  1013.                 lastresponse = 'n';
  1014.                 if (!k)
  1015.                     sprintf (here->Error, "%scan't close stream 0", SCONFail2);
  1016.                 else if (here->socket[k] <= 0)
  1017.                     sprintf (here->Error, "%sstream %d not connected", SCONFail2, k);
  1018.                 else {
  1019.                     lastresponse = 'y';
  1020.                     here->Error[0] = 0;
  1021.                     if (socklen (here->socket[k], 0))    /* discard any remaining input */
  1022.                         (void) recv_mbuf (here->socket[k], NULL, 0, NULLCHAR, 0);
  1023.                     (void) shutdown (here->socket[k], 1);
  1024.                     close_s (here->socket[k]);
  1025.                     if (Curproc->output == here->socket[k]) {
  1026.                         Curproc->output = here->socket[0];
  1027.                         here->user = here->whichsocket = 0;
  1028.                     }
  1029.                     here->socket[k] = 0;
  1030.                 }
  1031.                 break;
  1032.             case '#':
  1033.                 lastresponse = 'n';
  1034.                 if (k && here->socket[k] < 0)
  1035.                     sprintf (here->Error, "%sstream %d not connected", SCONFail, k);
  1036.                 else {
  1037.                     lastresponse = 'y';
  1038.                     Curproc->output = here->socket[k];
  1039.                     here->user = (k) ? here->socket[k] : 0;
  1040.                     here->whichsocket = k;
  1041.                 }
  1042.                 break;
  1043.             case '(':
  1044.                 lastresponse = 'n';
  1045.                 if (here->socket[k])
  1046.                     sprintf (here->Error, "%sstream %d already connected", SCONFail2, k);
  1047.                 else {
  1048.                     cp = skipnonwhite (cp);
  1049.                     cp = skipwhite (cp);
  1050.                     if ((here->socket[k] = cmdparse (sconcmds, cp, (void *) here)) != -1)
  1051.                         lastresponse = 'y';
  1052.                     else
  1053.                         here->socket[k] = 0;
  1054.                 }
  1055.                 break;
  1056.             case '=':
  1057.                 lastresponse = (here->socket[k] > 0) ? 'y' : 'n';
  1058.                 break;
  1059.             case '^':    /* convert string variable to upper/lower case */
  1060.                 cp++;
  1061.                 cp = skipwhite (cp);
  1062.                 if (*cp == 'l')
  1063.                     (void) strlwr (here->variables[k]);
  1064.                 else if (*cp == 'u')
  1065.                     (void) strupr (here->variables[k]);
  1066.                 break;
  1067.             default:
  1068.                 break;
  1069.         }
  1070.     }
  1071. lost:
  1072.     if (here->out != NULLFILE) {
  1073.         (void) fclose (here->out);
  1074.         here->out = NULLFILE;
  1075.     }
  1076.     free (label);
  1077.     /*    Curproc->output = here->socket[0]; */
  1078.     for (k = 0; k < 10; k++) {
  1079.         if (here->variables[k])
  1080.             if (!here->ischild || k < 5)
  1081.                 free (here->variables[k]);
  1082. #if 1
  1083.         if (disconexit && k && here->socket[k] > 0) {    /* free connected streams */
  1084.             if (socklen (here->socket[k], 0))    /* discard any remaining input */
  1085.                 (void) recv_mbuf (here->socket[k], NULL, 0, NULLCHAR, 0);
  1086.             (void) shutdown (here->socket[k], 1);
  1087.             close_s (here->socket[k]);
  1088.             here->socket[k] = 0;
  1089.         }
  1090. #endif
  1091.     }
  1092.     here->user = 0;
  1093.     here->whichsocket = 0;
  1094. }
  1095.  
  1096.  
  1097.  
  1098. static const char *tutorialName[] = { "Learning Center", "Information Center", "News Center" };
  1099. static const char banner[] = "For %s, connect to '%s' using the same path...\n";
  1100.  
  1101.  
  1102.  
  1103. static void
  1104. buildmenu (struct world *here)
  1105. {
  1106. FILE *fp;
  1107. char buf[80], buf2[256], *cp, *cp2;
  1108. struct ffblk ff;
  1109.  
  1110.     here->maxselect = 0;
  1111.     if (here->subdir)
  1112.         tprintf ("Current Sub-directory: %s\n\n", here->subdir);
  1113.     mycolorchange (here, "0F", here->last);
  1114.     tprintf ("\nWelcome to the ");
  1115.     mycolorchange (here, "0C", here->last);
  1116.     tprintf ("TNOS %s ", tutorialName[here->mode]);
  1117.     mycolorchange (here, "0F", here->last);
  1118.     tprintf ("at ");
  1119.     mycolorchange (here, "05", here->last);
  1120.     tprintf ("%s\n\n     %c", Hostname, here->subdir ? 'E' : '0');
  1121.     mycolorchange (here, "07", here->last);
  1122.     tprintf (" -  Exit %s\n", tutorialName[here->mode]);
  1123.     mycolorchange (here, "05", here->last);
  1124.     tprintf ("     %c", (here->subdir) ? '0' : 'C');
  1125.     mycolorchange (here, "07", here->last);
  1126.     if (here->subdir)
  1127.         tputs (" -  Return to Previous Menu\n");
  1128.     else
  1129.         tprintf (" -  %sable ANSI Color Graphics\n", (here->color) ? "Dis" : "En");
  1130.     sprintf (buf, "%s/%s*.tut", (here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "");
  1131.     if (findfirst (buf, &ff, 0) == 0) {
  1132.         do {
  1133.             kwait (NULL);    /* Let others run */
  1134.             cp2 = strrchr (ff.ff_name, '.');
  1135.             if (cp2)
  1136.                 *cp2 = '\0';
  1137.             sprintf (buf2, "%s/%s%s.tut", (here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "", ff.ff_name);
  1138.             if ((fp = fopen (buf2, READ_TEXT)) != NULLFILE) {
  1139.                 do {
  1140.                     (void) fgets (buf2, 256, fp);
  1141.                     cp = skipwhite (buf2);
  1142.                 } while (*cp == '\n');
  1143.                 (void) fclose (fp);
  1144.                 if (*cp == '~')    /* subdir directing file */
  1145.                     cp = skipwhite (skipnonwhite (skipwhite (++cp)));
  1146.                 here->Tutors[here->maxselect++] = strdup (ff.ff_name);
  1147.                 mycolorchange (here, "05", here->last);
  1148.                 tprintf ("    %2d", here->maxselect);
  1149.                 mycolorchange (here, "07", here->last);
  1150.                 tprintf (" -  %s", cp);
  1151.             }
  1152.             if (here->maxselect == 100)
  1153.                 break;
  1154.         } while (findnext (&ff) == 0);
  1155.     }
  1156. }
  1157.  
  1158.  
  1159.  
  1160. #ifdef MSDOS
  1161. #define SUBDIRSIZE 8
  1162. #else
  1163. #define SUBDIRSIZE 256
  1164. #endif
  1165.  
  1166.  
  1167.  
  1168. void
  1169. #ifndef STANDALONE
  1170. tutorserv (const char *call, struct mbx *m, int mode, int color, int ip)
  1171. #else
  1172. tutorserv (char *call, int mode, int color, int ip)
  1173. #endif
  1174. {
  1175. char selection[SUBDIRSIZE + 2], filename[80], *cp;
  1176. int k, sel, inited = 0;
  1177. struct world here;
  1178. #ifndef STANDALONE
  1179. char tmp[AXBUF];
  1180.  
  1181.     Tutored++;
  1182. #ifdef XSERVER
  1183.     xnotify (X_TUT);
  1184. #endif
  1185. #ifdef STATS_USE
  1186.     STATS_adduse (1);
  1187. #endif
  1188. #endif
  1189.     here.mode = mode;
  1190. #ifndef STANDALONE
  1191.     Tutorlogins[here.mode]++;
  1192. #endif
  1193.     here.maxselect = 0;
  1194.     here.call = call;
  1195. #ifndef STANDALONE
  1196.     here.m = m;
  1197. #endif
  1198.     here.subdir = NULLCHAR;
  1199. #ifndef STANDALONE
  1200.     (void) sockblock (Curproc->output, SOCK_NOTXBLOCK);    /* prevent backlogs ! */
  1201. #endif
  1202.     here.color = (char) color;
  1203.     here.ipconnect = (char) ip;
  1204.     here.inescape = 0;
  1205.     here.ischild = 0;
  1206.     here.lostconnection = 0;
  1207.     here.Error[0] = 0;
  1208.     here.out = NULLFILE;
  1209.     here.whichsocket = here.background = 0;
  1210.     here.socket = callocw (10, sizeof (int));
  1211.  
  1212.     here.user = here.socket[0] = Curproc->output;
  1213.     filename[0] = 0;
  1214.     if (m && color)
  1215.         memcpy (here.last, m->colorset, 2);
  1216.     else
  1217.         here.last[0] = 0;
  1218.     for ( ; ; ) {
  1219.         if (inited)
  1220.             tprintf ("\n\n\n\n");
  1221.         else
  1222.             inited = 1;
  1223.         buildmenu (&here);
  1224.         do {
  1225.             mycolorchange (&here, "0F", here.last);
  1226.             tprintf ("\nEnter Selection:\n");
  1227.             mygets (selection, 10, &here);
  1228.             if (here.lostconnection)
  1229.                 goto lost;
  1230.             kwait (NULL);
  1231.             if (toupper (*selection) == 'E') {
  1232.                 free (here.subdir);
  1233.                 here.subdir = NULLCHAR;
  1234.                 sel = 0;
  1235.                 break;
  1236.             }
  1237.             if (toupper (*selection) == 'C') {
  1238.                 sel = -1;
  1239.                 here.color ^= 1;
  1240.                 break;
  1241.             }
  1242.             sel = atoi (selection);
  1243.             if (!sel)
  1244.                 break;
  1245.             if (sel > here.maxselect)
  1246.                 tprintf ("Invalid number... select 0 - %-d!\007\n", here.maxselect);
  1247.         } while (sel > here.maxselect);
  1248.         if (sel == -1)
  1249.             continue;
  1250.         if (sel)
  1251.             sprintf (filename, "%s/%s%s.tut", (here.mode == 1) ? Info : (here.mode) ? News : Tutor, (here.subdir) ? here.subdir : "", here.Tutors[sel - 1]);
  1252.         for (k = 0; k < here.maxselect; k++)
  1253.             free (here.Tutors[k]);
  1254.         if (!sel) {
  1255.             if (!here.subdir)    /* not in a sub-directory! */
  1256.                 break;
  1257.             here.subdir[strlen (here.subdir) - 1] = 0;    /* take off last "/" */
  1258.             cp = strrchr (here.subdir, '/');
  1259.             if (!cp) {
  1260.                 free (here.subdir);
  1261.                 here.subdir = NULLCHAR;
  1262.             } else
  1263.                 *(++cp) = 0;
  1264.             continue;
  1265.         }
  1266.         if (!*filename || (here.fp = fopen (filename, READ_TEXT)) == NULLFILE) {
  1267.             tprintf ("Sorry, but something seems to be wrong with that tutorial!\n");
  1268.             continue;
  1269.         }
  1270.         /* Let's check first line to see if this file describes a sub-directory */
  1271.         (void) fgets (filename, 80, here.fp);
  1272.         cp = filename;
  1273.         if (*cp == '~') {    /* Yep! Sub-directory time! */
  1274.             cp = skipwhite (++cp);
  1275.             for (k = 0; k < SUBDIRSIZE && *cp && cp[k] != '\t' && cp[k] != ' '; k++)
  1276.                 selection[k] = cp[k];
  1277.             selection[k++] = '/';
  1278.             selection[k] = 0;
  1279.             k += (int) ((here.subdir) ? strlen (here.subdir) : 0);
  1280.             cp = (char *) mallocw ((unsigned) ++k);
  1281.             *cp = 0;
  1282.             if (here.subdir)
  1283.                 strcpy (cp, here.subdir);
  1284.             strcat (cp, selection);
  1285.             free (here.subdir);
  1286.             here.subdir = cp;
  1287.         } else {
  1288.             rewind (here.fp);
  1289.             for (k = 0; k < 10; k++) {
  1290.                 here.variables[k] = NULLCHAR;
  1291.                 here.indexes[k] = 0;
  1292.                 here.socket[k] = 0;
  1293.             }
  1294.             process (&here);
  1295.         }
  1296.         (void) fclose (here.fp);
  1297.     }
  1298.     mycolorchange (&here, "09", here.last);
  1299.     tprintf ("\n\nThanks for using the ");
  1300.     mycolorchange (&here, "0C", here.last);
  1301.     tprintf ("TNOS %s ", tutorialName[here.mode]);
  1302.     mycolorchange (&here, "09", here.last);
  1303.     tprintf ("at ");
  1304.     mycolorchange (&here, "0E", here.last);
  1305.     tprintf ("%s\n\n", Hostname);
  1306.     mycolorchange (&here, "0F", here.last);
  1307.     if (m)
  1308.         mycolorchange (&here, m->colorset, here.last);
  1309. #ifndef STANDALONE
  1310.     (void) pax25 (tmp, Tcall);
  1311.     if (*tmp && mode && Stutor != -1)    /* if tutor server active, but not 'us */
  1312.         tprintf (banner, "tutorial assistance", tmp);
  1313.     (void) pax25 (tmp, Icall);
  1314.     if (*tmp && mode != 1 && Sinfo != -1)    /* if info server active, but not 'us' */
  1315.         tprintf (banner, "local/area information", tmp);
  1316.     (void) pax25 (tmp, Ncall);
  1317.     if (*tmp && mode != 2 && Snews != -1)    /* if news server active, but not 'us' */
  1318.         tprintf (banner, "Ham related NEWS", tmp);
  1319.     tputc ('\n');
  1320.     usflush (Curproc->output);
  1321.     (void) sockblock (Curproc->output, SOCK_BLOCK);
  1322.     free (here.socket);
  1323. #endif
  1324.       lost:
  1325. #ifndef STANDALONE
  1326.     Tutored--;
  1327. #ifdef XSERVER
  1328.     xnotify (X_TUT);
  1329. #endif
  1330. #endif
  1331. }
  1332.  
  1333.  
  1334.  
  1335. extern char NoRead[];
  1336. static short scriptmode = 0;
  1337. static struct mbx *MbxCalling = NULLMBX;
  1338. static short numCalling = 0;
  1339. static char const **argsCalling;
  1340. static short proxyServer = 0;
  1341.  
  1342.  
  1343.  
  1344. static int
  1345. scriptcmd (
  1346. struct world *inherited,    /* non-zero, inherited world */
  1347. FILE *fp,
  1348. const char *name
  1349. ) {
  1350. struct session *sp = NULLSESSION;
  1351. int usesession = 0, k;
  1352. struct world here;
  1353.  
  1354.     /* Use a session if this comes from console - WG7J*/
  1355.     if (!inMbScriptHook && !scriptmode && Curproc->input == Command->input) {
  1356.         usesession = 1;
  1357.         if ((sp = newsession (name, SCRIPT, 0)) == NULLSESSION) {
  1358.             return 1;
  1359.         }
  1360.     }
  1361.     inMbScriptHook = 0;
  1362.     here.background = scriptmode;
  1363.     if (!inherited || inherited == (struct world *) -1) {
  1364.         here.ischild = 0;
  1365.         here.user = 0;
  1366.         here.whichsocket = 0;
  1367.         here.ipconnect = 1;
  1368.         here.goback = 0;
  1369.         here.socket = callocw (10, sizeof (int));
  1370.  
  1371. #ifndef STANDALONE
  1372.         if (inherited == (struct world *) -1) {
  1373.             here.m = MbxCalling;
  1374.             if (here.m)
  1375.                 here.call = here.m->name;
  1376.             else
  1377.                 here.call = "noname";
  1378.             MbxCalling = NULLMBX;
  1379.         } else {
  1380.             here.m = NULLMBX;
  1381. #endif
  1382.             here.call = "noname";
  1383. #ifndef STANDALONE
  1384.         }
  1385. #endif
  1386.         for (k = 0; k < 10; k++) {
  1387.             here.indexes[k] = 0;
  1388.             here.variables[k] = NULLCHAR;
  1389.         }
  1390.         if (inherited == (struct world *) -1) {
  1391.             for (k = 0; k < numCalling; k++)
  1392.                 here.variables[k] = strdup (argsCalling[k]);
  1393.             here.indexes[0] = numCalling;
  1394.             inherited = 0;
  1395.             if (proxyServer)
  1396.                 here.goback = proxyServer;
  1397.             proxyServer = 0;
  1398.         }
  1399.     } else {
  1400.         here.ischild = 1;
  1401.         here.user = inherited->user;
  1402.         here.whichsocket = inherited->whichsocket;
  1403.         here.ipconnect = inherited->ipconnect;
  1404.         here.goback = inherited->goback;
  1405.         here.socket = inherited->socket;
  1406.         here.call = inherited->call;
  1407.         if (inherited->background)
  1408.             here.background = inherited->background;
  1409. #ifndef STANDALONE
  1410.         here.m = inherited->m;
  1411. #endif
  1412.         for (k = 0; k < 10; k++) {
  1413.             here.indexes[k] = inherited->indexes[k];
  1414.             if (inherited->variables[k])
  1415.                 here.variables[k] = strdup (inherited->variables[k]);
  1416.             else
  1417.                 here.variables[k] = NULLCHAR;
  1418.         }
  1419.     }
  1420.     here.fp = fp;
  1421.     here.mode = 0;
  1422.     here.maxselect = 0;
  1423.     here.subdir = NULLCHAR;
  1424.     here.color = 0;
  1425.     here.lostconnection = 0;
  1426.     here.out = NULLFILE;
  1427.     here.inescape = 0;
  1428.     here.last[0] = 0;
  1429.     here.Error[0] = 0;
  1430.     process (&here);
  1431.     (void) fclose (here.fp);
  1432.     if (inherited) {
  1433.         for (k = 5; k < 10; k++) {
  1434.             if (!here.goback) {
  1435.                 if (inherited->variables[k])
  1436.                     free (inherited->variables[k]);
  1437.                 inherited->variables[k] = NULLCHAR;
  1438.                 if (here.variables[k])
  1439.                     inherited->variables[k] = here.variables[k];
  1440.                 inherited->indexes[k] = here.indexes[k];
  1441.             } else
  1442.                 free (here.variables[k]);
  1443.         }
  1444.         if (!here.goback)
  1445.             inherited->whichsocket = here.whichsocket;
  1446.     } else
  1447.         free (here.socket);
  1448.     if (usesession) {
  1449.         (void) keywait (NULLCHAR, 1);
  1450.         freesession (sp);
  1451.     }
  1452.     return 0;
  1453. }
  1454.  
  1455.  
  1456.  
  1457. int
  1458. doscript (int argc, char *argv[], void *p)
  1459. {
  1460. FILE *fp;
  1461. int oldin, oldout;
  1462. int thisscriptmode;
  1463.  
  1464.     {
  1465.     char fname[256];
  1466.  
  1467.         strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 256);
  1468.         if ((fp = fopen (fname, READ_TEXT)) == NULLFILE) {
  1469.             tprintf (NoRead, fname, SYS_ERRLIST(errno));
  1470.             return 1;
  1471.         }
  1472.     }
  1473.  
  1474.     scriptmode = (argc > 2 && !strnicmp (argv[2], "back", 4)) ? 1 :
  1475.         (!argc && ((struct world *) p)->goback) ? 1 : 0;
  1476.     oldin = Curproc->input;
  1477.     oldout = Curproc->output;
  1478.     if (scriptmode)
  1479.         Curproc->input = Curproc->output = -1;
  1480.     thisscriptmode = scriptmode;
  1481.     if (!inMbScriptHook && (scriptmode || Curproc->input == Command->input))
  1482.         (void) newproc ("script", 2048, (void (*)(int, void *, void *)) scriptcmd, (argc > 1) ? 0 : (int) p, (void *) fp, (void *) strdup (argv[1]), 2);
  1483.     else
  1484.         (void) scriptcmd ((argc > 1) ? 0 : (struct world *) p, fp, argv[1]);
  1485.  
  1486.     if (thisscriptmode) {
  1487.         Curproc->input = oldin;
  1488.         Curproc->output = oldout;
  1489.     }
  1490.     return 0;
  1491. }
  1492.  
  1493.  
  1494.  
  1495.  
  1496. #ifndef STANDALONE
  1497. int
  1498. dombscript (int argc, char *argv[], void *p)
  1499. {
  1500. struct mbx *m;
  1501. char *args[2], buffer[128];
  1502.  
  1503.     m = (struct mbx *) p;
  1504.     if (argc == 1) {
  1505.         /* listing of commands available */
  1506.         (void) DisplayFile (UCmdsHelp, m->user);
  1507.         return 0;
  1508.     }
  1509.     sprintf (buffer, "%s/%s.cmd", UserCmds, argv[1]);
  1510.     if (!access (buffer, 4)) {
  1511.         args[1] = buffer;
  1512.         numCalling = (short int) (argc - 2);
  1513.         if (numCalling > 10)
  1514.             numCalling = 10;
  1515.         argsCalling = (char const **) &argv[2];
  1516.         MbxCalling = m;
  1517.         (void) doscript (1, args, (void *) -1);
  1518.     } else {
  1519.         tprintf ("Unknown CMD: '%s'\n", argv[1]);
  1520.         (void) DisplayFile (UCmdsHelp, m->user);
  1521.     }
  1522.     return 0;
  1523. }
  1524.  
  1525.  
  1526.  
  1527. void
  1528. mbscripthook (struct mbx *m, const char *hookfile)
  1529. {
  1530. char *args[2], buffer[128];
  1531. char *args2[2];
  1532.  
  1533.     sprintf (buffer, "%s/%s", UserCmds, hookfile);
  1534.     if (!access (buffer, 4)) {
  1535.         args[1] = buffer;
  1536.         numCalling = 1;
  1537.         args2[0] = m->line;
  1538.         argsCalling = (char const **) &args2[0];    /*lint !e789 */
  1539.         MbxCalling = m;
  1540.         inMbScriptHook = 1;
  1541.         (void) doscript (1, args, (void *) -1);
  1542.     }
  1543. }
  1544.  
  1545.  
  1546.  
  1547. int
  1548. proxy (FILE *fp, const char *from OPTIONAL)
  1549. {
  1550. char buf[512], subject[256], realfrom[128], *cp;
  1551. long startat;
  1552. FILE *out;
  1553. char const *args[2];
  1554. int oldin, oldout;
  1555. int skiptoblank = 0;
  1556.  
  1557.     parseheader (fp, realfrom, subject, NULLCHAR, NULLCHAR, buf, &startat);
  1558.     cp = strchr (realfrom, '@');
  1559.     if (cp)
  1560.         *cp = 0;
  1561.     sprintf (buf, "%s/proxy.tmp", Spool);
  1562.     out = fopen (buf, "w");
  1563.     if (out == NULLFILE)
  1564.         return 1;
  1565.     fprintf (out, "[%s]\n", realfrom);
  1566.     fseek (fp, startat, SEEK_SET);
  1567.     while (fgets (buf, 512, fp) != NULLCHAR) {
  1568.         if (!strncmp ("Message-Id: ", buf, 12))
  1569.             skiptoblank = 1;
  1570.         else {
  1571.             if (skiptoblank && buf[0] == '\n')
  1572.                 skiptoblank = 0;
  1573.             else if (!skiptoblank)
  1574.                 fputs (buf, out);
  1575.         }
  1576.     }
  1577.     (void) fclose (out);
  1578.     numCalling = 1;
  1579.     argsCalling = args;    /*lint !e789 */
  1580.     args[0] = "import";
  1581.  
  1582.     sprintf (buf, "%s/proxy.cmd", UserCmds);
  1583.     if ((out = fopen (buf, READ_TEXT)) == NULLFILE)
  1584.         return 1;
  1585.  
  1586.     oldin = Curproc->input;
  1587.     oldout = Curproc->output;
  1588.     Curproc->input = Curproc->output = -1;
  1589.     scriptmode = 1;
  1590.     proxyServer = 1;
  1591.  
  1592. #if 0
  1593.     newproc ("script", 2048, (void (*)(int, void *, void *)) scriptcmd, (int) -1, (void *) out, (void *) strdup ("Proxy"), 2);
  1594. #else
  1595.     (void) scriptcmd ((struct world *) -1, out, "Proxy");
  1596. #endif
  1597.     Curproc->input = oldin;
  1598.     Curproc->output = oldout;
  1599.     return 1;
  1600. }
  1601. #endif
  1602.  
  1603.  
  1604. #endif
  1605.